package cn.mujiankeji.mbrowser.app

import android.app.PictureInPictureParams
import android.os.Build
import android.util.Log
import androidx.compose.runtime.Composable
import androidx.compose.runtime.State
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateListOf
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.setValue
import androidx.compose.runtime.snapshots.SnapshotStateList
import androidx.compose.ui.unit.dp
import cn.mujiankeji.mbrowser.工具.mlog
import cn.mujiankeji.mbrowser.数据.数据库.AppDatabase
import cn.mujiankeji.mbrowser.界面.标签页.网页.网页标签状态
import cn.mujiankeji.mbrowser.界面.框架.主视图.窗口页状态
import cn.mujiankeji.mbrowser.界面.框架.主视图.标签页状态
import cn.mujiankeji.mbrowser.界面.框架.小窗视图.小窗状态
import com.blankj.utilcode.util.ActivityUtils
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.SupervisorJob
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.asStateFlow
import kotlinx.coroutines.launch

/**
 * 界面相关信息
 */
class 界面模块(val database: AppDatabase) {

    // 创建专用的协程作用域，用于处理异步任务和状态更新
    val viewModelScope = CoroutineScope(SupervisorJob() + Dispatchers.Main)

    // 全局加载中状态控制
    var 显示加载中界面 by mutableStateOf(false)
    var 加载中提示文本 by mutableStateOf("")

    // 屏幕信息
    var 屏宽 by mutableStateOf(1.dp)
    var 屏高 by mutableStateOf(1.dp)

    // --- 窗口管理 -- 主内容 ---
    // 持有所有窗口的列表
    val 窗口列表: SnapshotStateList<窗口页状态> = mutableStateListOf()

    // 私有的、可变的当前活动窗口索引 State
    private val _当前活动窗口索引 = mutableStateOf(0)
    val 当前活动窗口索引: State<Int> = _当前活动窗口索引

    // 公开的、只读的当前活动窗口状态 Flow
    private val _当前活动窗口 = MutableStateFlow<窗口页状态?>(null)
    val 当前活动窗口: StateFlow<窗口页状态?> = _当前活动窗口.asStateFlow()

    // 主要UI状态变量
    var 标题 by mutableStateOf("")
    var 地址 by mutableStateOf("")
    var 进度 by mutableStateOf(0)
    var 可否前进 by mutableStateOf(false) // 前进导航是否可用
    var 可否后退 by mutableStateOf(false) // 后退导航是否可用
    var 当前标签页 by mutableStateOf<标签页状态?>(null)
    var 显示菜单 by mutableStateOf(false)

    /**
     * 触发状态更新事件
     *
     * 通知UI组件进行刷新或其他操作
     */
    fun 状态更新(){
        mlog("状态更新 - 标题:[$标题] 地址:[$地址] 进度:[$进度] 前进:[$可否前进] 后退:[$可否后退]")
    }


    // --- 小窗管理 ---
    var 小窗列表 = mutableStateListOf<小窗状态>()
    fun 添加小窗(小窗 : 小窗状态){
        if (!小窗列表.contains(小窗)){
            小窗列表.add(小窗)
        }
    }
    fun 移除小窗(小窗 : 小窗状态?){
        if (小窗 == null) 小窗列表.clear()
        else 小窗列表.remove(小窗)
    }


    suspend fun 更新可否前进后退(窗口 : 窗口页状态){
        可否前进 = 窗口.可否前进()
        可否后退 = 窗口.可否后退()
    }

    // --- 初始化 ---
    init {
        创建窗口()

        // 监听当前活动窗口及其活动标签页，更新UI状态
        viewModelScope.launch {
            当前活动窗口.collect { window ->
                if (window == null) {
                    // 如果没有活动窗口，重置状态
                    标题 = ""
                    地址 = ""
                    进度 = 0
                    可否前进 = false
                    可否后退 = false
                    当前标签页 = null
                    return@collect
                }

                // 启动单独的协程来收集标签页状态，避免阻塞窗口状态收集
                launch {
                    window.当前活动标签页.collect { tab ->
                        当前标签页 = tab

                        if (tab == null) {
                            标题 = ""
                            地址 = ""
                            进度 = 0
                            return@collect
                        }

                        更新可否前进后退(window)

                        // 协程监听页面可否前进后退（页面自身）
                        launch {
                            tab.可否后退.collect{
                                更新可否前进后退(window)
                            }
                        }
                        launch {
                            tab.可否前进.collect{
                                更新可否前进后退(window)
                            }
                        }

                        // 启动协程监听标题和地址变化
                        launch {
                            tab.标题.collect { newTitle ->
                                newTitle?.let { 标题 = it }
                            }
                        }

                        launch {
                            tab.地址.collect { newUrl ->
                                newUrl?.let { 地址 = it }
                            }
                        }

                        // 监听加载进度
                        launch {
                            // 使用对MutableState的直接访问
                            tab.加载进度.collect{
                                进度 = it
                            }
                        }
                    }
                }
            }
        }
    }


    // --- 主内容 ---

    /**
     * 添加一个新的窗口。
     */
    fun 创建窗口(默认标签页 : 标签页状态 ?= null) : 窗口页状态 {
        val 新窗口 = 窗口页状态().apply {
            默认标签页?.let {创建标签页(it) }
        }
        窗口列表.add(新窗口)
        // 切换到新创建的窗口，并确保它有一个初始标签页
        切换窗口(窗口列表.lastIndex)
        return 新窗口
    }

    /**
     * 移除指定ID的窗口。
     */
    fun 移除窗口(窗口ID: String) {
        val indexToRemove = 窗口列表.indexOfFirst { it.id == 窗口ID }
        if (indexToRemove != -1) {
            val removedWindow = 窗口列表.removeAt(indexToRemove)
            Log.d("界面状态", "移除了窗口: ${removedWindow.id}, 剩余窗口: ${窗口列表.size}")

            if (窗口列表.isEmpty()) {
                Log.d("界面状态", "所有窗口都已移除，添加一个新窗口")
                创建窗口() // 创建一个新窗口并自动切换
            } else {
                // 如果移除的是当前活动窗口，或者移除后当前活动窗口索引失效
                val newActiveIndex = when {
                    _当前活动窗口索引.value == indexToRemove -> {
                        // 尝试切换到前一个，如果不存在则切换到新的第一个
                        (indexToRemove - 1).coerceAtLeast(0).coerceAtMost(窗口列表.size - 1)
                    }
                    _当前活动窗口索引.value > indexToRemove -> {
                        // 移除的是当前活动窗口之前的窗口，索引需要减一
                        (_当前活动窗口索引.value - 1).coerceAtLeast(0)
                    }
                    else -> {
                        // 移除的是当前活动窗口之后的窗口，或者索引本身就超出了（理论上不应发生）
                        // 确保索引在有效范围内
                        _当前活动窗口索引.value.coerceIn(0, (窗口列表.size - 1).coerceAtLeast(0))
                    }
                }
                Log.d("界面状态", "移除窗口后，尝试切换到索引: $newActiveIndex")
                切换窗口(newActiveIndex)
            }
        } else {
            Log.w("界面状态", "尝试移除窗口失败，未找到ID: $窗口ID")
        }
    }

    /**
     * 切换到指定索引的窗口。
     * @param 索引 窗口列表中的索引
     */
    fun 切换窗口(索引: Int) {
        if (索引 in 窗口列表.indices) {
            _当前活动窗口索引.value = 索引
            更新当前活动窗口Flow()
            val activeWindow = 当前活动窗口.value
            activeWindow?.界面被恢复()

            // 立即更新前进后退状态
            activeWindow?.let { window ->
                viewModelScope.launch {
                    更新可否前进后退(window)
                }

                // 立即更新当前标签页
                window.当前活动标签页.value?.let { tab ->
                    当前标签页 = tab

                    // 更新基本信息
                    tab.标题.value?.let { 标题 = it }
                    tab.地址.value?.let { 地址 = it }
                    进度 = tab.加载进度.value
                }
            }
        }
    }

    /**
     * 更新内部的 _当前活动窗口 StateFlow。
     */
    private fun 更新当前活动窗口Flow() {
        val window = 窗口列表.getOrNull(_当前活动窗口索引.value)
        _当前活动窗口.value = window
    }

    fun 加载(页面 : 标签页状态){
        移除小窗(null) // 打开新页面则 关闭所有小窗 --
        当前活动窗口.value?.创建标签页(页面)
    }

    /**
     * 加载URL
     */
    fun 加载(url: String, referer : String = "",newWindow : Boolean = false) {
        if (newWindow){
            创建窗口(网页标签状态(url,referer))
        }
        else{
            当前活动窗口.value?.创建网页标签页(url,referer)

            // 确保更新状态
            viewModelScope.launch {
                // 短暂延迟确保标签页创建完成
                kotlinx.coroutines.delay(100)
                更新当前活动窗口Flow()
            }
        }

    }

    fun 刷新() {
        当前标签页?.刷新()

        // 短暂延迟后更新状态，以便反映刷新开始
        viewModelScope.launch {
            kotlinx.coroutines.delay(50)
            // 强制将进度设为0，表示开始刷新
            进度 = 0
            状态更新()
        }
    }
    fun 后退() {
        // 优先小窗
        if (小窗列表.isNotEmpty()){
            小窗列表.removeAt(小窗列表.size - 1)
            return
        }

        // 主内容
        if (当前活动窗口.value?.后退() == true) {
            // 成功后退，更新状态
            viewModelScope.launch {
                kotlinx.coroutines.delay(50)
                当前活动窗口.value?.let { window ->
                    更新可否前进后退(window)
                    window.当前活动标签页.value?.let { tab ->
                        当前标签页 = tab
                        tab.标题.value?.let { 标题 = it }
                        tab.地址.value?.let { 地址 = it }
                    }
                }
                // 刷新开始时进度置0
                进度 = 0
                状态更新()
            }
            return
        }

        // 如果后退失败，尝试切换到前一个窗口
        if (_当前活动窗口索引.value > 0) {
            切换窗口(_当前活动窗口索引.value - 1)
        }
        else if (窗口列表.size > 1) {
            切换窗口(0)
        }
        else{
            创建窗口()
        }
        状态更新()
    }
    fun 前进() {
        if (当前活动窗口.value?.前进() == true) {
            // 成功前进，更新状态
            viewModelScope.launch {
                kotlinx.coroutines.delay(50)
                当前活动窗口.value?.let { window ->
                    更新可否前进后退(window)
                    window.当前活动标签页.value?.let { tab ->
                        当前标签页 = tab
                        tab.标题.value?.let { 标题 = it }
                        tab.地址.value?.let { 地址 = it }
                    }
                }
                // 刷新开始时进度置0
                进度 = 0
                状态更新()
            }
        }
    }


    //  @parent 参数 Boolean   true 则表示全屏状态中，为false 则表示全屏结束(Disposable)并该变量被置空了
    var 全屏视图 by mutableStateOf<(@Composable ()->Unit)?>(null)
        private set
    fun 设置全屏视图(content : @Composable ()->Unit){
        全屏视图 = content
    }
    fun 取消全屏(){
        全屏视图 = null
    }

    var 画中画关闭事件 by mutableStateOf<(()->Unit)?>(null)
    fun 设置画中画(onClose : () -> Unit,content : @Composable ()->Unit){
        画中画关闭事件 = onClose
        全屏视图 = content
        val activity = ActivityUtils.getTopActivity()
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
            activity.setPictureInPictureParams(PictureInPictureParams.Builder()
                .setSeamlessResizeEnabled(true)
                .setAutoEnterEnabled(true)
                .build())
        }
        else {
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
                activity.enterPictureInPictureMode(PictureInPictureParams.Builder()
                    .build())
            }
        }



    }

    /**
     * 关闭当前标签页
     * 如果关闭的是最后一个标签页，则根据窗口数量进行处理：
     * - 如果只有一个窗口，则创建一个新的默认标签页
     * - 如果有多个窗口，则关闭当前窗口
     * @return 是否成功关闭标签页
     */
    fun 关闭当前标签页(): Boolean {
        val 当前窗口 = 当前活动窗口.value ?: return false
        val 当前标签页索引 = 当前窗口.当前活动标签页索引.value
        
        // 调用窗口的移除标签页方法
        val 成功 = 当前窗口.移除标签页(当前标签页索引)
        
        // 如果关闭后窗口没有标签页，并且有多个窗口，则关闭该窗口
        if (成功 && 当前窗口.标签页列表.isEmpty() && 窗口列表.size > 1) {
            移除窗口(当前窗口.id)
        }
        
        return 成功
    }
    
    /**
     * 关闭指定标签页
     * @param 标签页ID 要关闭的标签页ID
     * @return 是否成功关闭标签页
     */
    fun 关闭标签页(标签页ID: String): Boolean {
        val 当前窗口 = 当前活动窗口.value ?: return false
        
        // 调用窗口的移除标签页方法
        val 成功 = 当前窗口.移除标签页(标签页ID)
        
        // 如果关闭后窗口没有标签页，并且有多个窗口，则关闭该窗口
        if (成功 && 当前窗口.标签页列表.isEmpty() && 窗口列表.size > 1) {
            移除窗口(当前窗口.id)
        }
        
        return 成功
    }

}